/*
 * @Version: V1.0
 * @Project: MGS组件 All rights Reserved, Designed By www.supermap.com
 * @Title:
 * @Package: mgs-webui-basic
 * @Description:
 * @Author: 李卫欣
 * @Date: 2021-06-20 23:00:11
 * @Copyright: 2021 www.supermap.com Inc. All rights reserved.
 * @注意: 本内容仅限于北京超图信息技术有限公司内部传阅，禁止外泄以及用于其他的商业目的
 */
import type { BindMap } from 'types'
import L from 'leaflet'
import {
    getCGCS2000Prj,
    getWGS84_CGCS2000,
    getCGCS2000FDXFromLng,
} from '@/utils/projection'

export default class KilometerGridPlugin {
    static extends = [
        'openKilometerGrid', //打开公里网
        'closeKilometerGrid', //关闭公里网
        'openKGLabel', //打开公里网注记(没有公里网时，会开启公里网)
        'closeKGLabel', //关闭公里网注记
    ]

    //注记显示开关
    private showKGLable__!: Boolean

    //地图对象Cesium.viewer
    private map: any

    //内存绘制层
    private kilometerGridGroup__ = L.layerGroup()

    //内存绘注记制层
    private kGLabelGroup__ = L.layerGroup()

    //公里网显示开关
    private isOpen__ = false

    //当前视口范围
    private currentBounds__!: L.LatLngBounds

    //当前视口比例
    private currentZoomLvl__ = 1

    //插件归属的vue对象
    private vmParent: any

    //公里网 样式
    private kilometerGridStyle__: any

    constructor(vm: BindMap) {
        this.vmParent = vm
        this.map = vm.map
        this.kilometerGridGroup__.addTo(this.map)
        this.kGLabelGroup__.addTo(this.map)
        this.currentBounds__ = this.map.getBounds()
        this.currentZoomLvl__ = this.map.getZoom()
        this.showKGLable__ = false
    }

    /**
     * 打开公里网
     */
    openKilometerGrid(isLabel: boolean = false, style: any) {
        this.isOpen__ = true
        this.showKGLable__ = isLabel
        this.kilometerGridStyle__ = style
        this.map.on('zoomend', this._onMapZoomEnd, this)
        this.map.on('moveend', this._onMapMoveEnd, this)
        this.drawKilometerGrid(this.currentZoomLvl__, this.currentBounds__)
    }

    /**
     * 关闭公里网
     */
    closeKilometerGrid() {
        this.isOpen__ = false
        this.showKGLable__ = false
        this.kilometerGridStyle__ = {}
        this.map.off('zoomend', this._onMapZoomEnd)
        this.map.off('moveend', this._onMapMoveEnd)
        this.kilometerGridGroup__.clearLayers()
        this.kGLabelGroup__.clearLayers()
    }

    /**
     * 打开公里网注记
     */
    openKGLabel() {
        this.showKGLable__ = true
        this.closeKilometerGrid()
        this.openKilometerGrid(true, this.kilometerGridStyle__)
    }

    /**
     * 关闭公里网注记
     */
    closeKGLabel() {
        this.showKGLable__ = false
        // this.closeKilometerGrid()
        // this.openKilometerGrid()
        this.kGLabelGroup__.clearLayers()
    }

    /**
     * 地图比例尺改变事件
     * @param e
     * @returns
     */
    _onMapZoomEnd(e: any) {
        this.currentBounds__ = e.target.getBounds()
        this.currentZoomLvl__ = e.target.getZoom()
        if (!this.isOpen__) {
            return
        }
        this.drawKilometerGrid(e.target.getZoom(), e.target.getBounds())
    }

    /**
     * 地图中心点改变事件
     * @param e
     * @returns
     */
    _onMapMoveEnd(e: any) {
        this.currentBounds__ = e.target.getBounds()
        this.currentZoomLvl__ = e.target.getZoom()
        if (!this.isOpen__) {
            return
        }
        this.drawKilometerGrid(this.map.getZoom(), this.map.getBounds())
    }

    /**
     * 绘制经纬网
     * @param zoomLvl 当前级别
     * @param bounds 当前范围
     */
    drawKilometerGrid(zoomLvl: number, bounds: L.LatLngBounds) {
        //清除原网格
        this.kilometerGridGroup__.clearLayers()
        this.kGLabelGroup__.clearLayers()
        //设置风格样式
        const selfStyle = Object.assign(
            {
                color: '#999999',
                fillColor: 'transparent',
                weight: 0.5,
                'font-size': '16px',
                'font-weight': 400,
            },
            this.kilometerGridStyle__
        )
        this.kilometerGridStyle__ = selfStyle
        //计算跨度
        let step: number = 1000
        let deltaPX: number = 500
        if (this.currentZoomLvl__ < 5) {
            step = 500000
            deltaPX = 30
        } else if (this.currentZoomLvl__ < 7) {
            step = 200000
            deltaPX = 100
        } else if (this.currentZoomLvl__ < 9) {
            step = 100000
            deltaPX = 300
        } else if (this.currentZoomLvl__ < 12) {
            step = 10000
            deltaPX = 300
        }
        //按CGCS高斯投影6度带绘制
        let w: number = bounds.getWest()
        let s: number = bounds.getSouth()
        let e: number = bounds.getEast()
        let n: number = bounds.getNorth()
        //保留刻度点坐标
        let lbW = w
        if (lbW < 72) {
            lbW = 72
        }
        let lbN = n
        if (lbN > 56) {
            lbN = 56
        }
        //扩展视口范围
        const lbpt = this.map.latLngToContainerPoint(L.latLng(s, w))
        const rtpt = this.map.latLngToContainerPoint(L.latLng(n, e))
        lbpt.x -= deltaPX
        lbpt.y += deltaPX
        rtpt.x += deltaPX
        rtpt.y -= deltaPX
        const sw = this.map.containerPointToLatLng(lbpt)
        const ne = this.map.containerPointToLatLng(rtpt)
        w = sw.lng
        s = sw.lat
        e = ne.lng
        n = ne.lat
        //w 72 s 138
        if (w < 72) {
            w = 72
        }
        if (s < 10) {
            s = 4
        }
        if (e > 138) {
            e = 138
        }
        if (n > 56) {
            n = 56
        }
        //坐标转换
        const posStart = getCGCS2000Prj([w, s])
        const posEnd = getCGCS2000Prj([e, n])
        let r = 0,
            c = 0
        let oldline: number[][] = []
        const dh_arr: number[] = []
        const self = this
        //组织方里网
        for (
            let x: number = Math.floor(posStart[0] / step) * step;
            x < posEnd[0] + step;
            x += step
        ) {
            let latlngTmp: any
            try {
                latlngTmp = getWGS84_CGCS2000([x, posStart[1]])
            } catch {
                continue
            }
            if (latlngTmp[0] < w) continue
            if (latlngTmp[0] > e) continue
            const newLine: number[][] = []
            for (
                let y: number = Math.floor(posStart[1] / step) * step;
                y < posEnd[1] + step;
                y += step
            ) {
                const latlng = getWGS84_CGCS2000([x, y])
                newLine.push(latlng)
                if (r > 0 && c > 0) {
                    L.polygon(
                        [
                            [oldline[c - 1][1], oldline[c - 1][0]],
                            [newLine[c - 1][1], newLine[c - 1][0]],
                            [latlng[1], latlng[0]],
                            [oldline[c][1], oldline[c][0]],
                        ],
                        selfStyle
                    )
                        .addTo(this.kilometerGridGroup__)
                        .on('click', function (e) {
                            self.vmParent.$emit('KilometerGridClick', e)
                        })
                    //添加刻度
                    if (this.showKGLable__) {
                        // 拼接样式字符串
                        let styleHtml = ``
                        for (const key in selfStyle) {
                            styleHtml += `${key}:${selfStyle[key]};`
                        }
                        if (r === 1) {
                            //纬度
                            const strY: string = y + ''
                            L.marker([latlng[1], lbW], {
                                icon: L.divIcon({
                                    className: '',
                                    html: `<span style='margin-left:10px;${styleHtml}'>${strY.substring(
                                        0,
                                        2
                                    )}(${strY.substring(2, 5)})</span>`,
                                    // html: `<span style='margin-left:10px;${styleHtml}'>${strY}</span>`,
                                    //     html: `<span style='margin-left:10px;${styleHtml}'>${strY.substring(
                                    //     0,
                                    //     2
                                    // )}</span><span style='${styleHtml}'>${strY.substring(
                                    //     2
                                    // )}</span>`,
                                }),
                            }).addTo(this.kGLabelGroup__)
                        }
                        if (c === 1) {
                            //经度
                            const strX: string = x + ''
                            const dh: number = getCGCS2000FDXFromLng(latlng[0])
                            if (dh !== 0) {
                                if (!dh_arr.includes(dh)) {
                                    dh_arr.push(dh)
                                    L.marker([lbN, latlng[0]], {
                                        icon: L.divIcon({
                                            className: '',
                                            html: `<span style='margin-top:5px;display:inline-block;${styleHtml}'>${dh}d(${latlng[0]}°)</span>`,
                                            // html: `<span style='margin-top:5px;display:inline-block;${styleHtml}'>${dh}</span><span style='${styleHtml}'>d(${latlng[0]}°)</span>`,
                                        }),
                                    }).addTo(this.kGLabelGroup__)
                                }
                            } else {
                                L.marker([lbN, latlng[0]], {
                                    icon: L.divIcon({
                                        className: '',
                                        html: `<span style='margin-top:5px;display:inline-block;${styleHtml}'>${strX.substring(
                                            0,
                                            2
                                        )}(${strX.substring(2, 5)})</span>`,
                                        // html: `<span style='margin-top:5px;${styleHtml}'>${strX.substring(
                                        //     0,
                                        //     2
                                        // )}</span><span style='${styleHtml}'>${strX.substring(
                                        //     2
                                        // )}</span>`,
                                    }),
                                }).addTo(this.kGLabelGroup__)
                            }
                        }
                    }
                }
                c++
            }
            oldline = newLine
            r++
            c = 0
        }
    }
}
